<?php
declare(strict_types=1);

namespace App\Middleware\AdminApi;

use App\Utils\CustomUtils;
use Hyperf\HttpServer\Contract\ResponseInterface as HttpResponse;
use Hyperf\Utils\Context;
use Phper666\JWTAuth\Exception\TokenValidException;
use Phper666\JWTAuth\JWT;
use Phper666\JWTAuth\Middleware\JWTAuthMiddleware;
use Phper666\JWTAuth\Util\JWTUtil;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
use App\Constants\XZXResponseCode;
use App\Exception\XZXValidationException;
use App\Service\SysAdminService;
use Hyperf\Di\Annotation\Inject;

class AdminJWTAuthMiddleware extends JWTAuthMiddleware
{
    /**
     * @var HttpResponse
     */
    protected $response;

    protected $jwt;

    /**
     * @var SysAdminService
     * @Inject()
     */
    protected $SysAdminService;

    public function __construct(HttpResponse $response, JWT $jwt)
    {
        parent::__construct($response, $jwt);
    }

    /**
     * @param ServerRequestInterface  $request
     * @param RequestHandlerInterface $handler
     * @return ResponseInterface
     * @throws \Psr\SimpleCache\InvalidArgumentException
     * @throws \Throwable
     */
    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
    {
        // $request = $request->withAttribute("ext", [
        //     "user"        => '',
        //     "createBy"    => 'admin',
        //     "uid"         => '029928e4-3094-11ea-9b31-702084fbc6aa',
        //     "roleId"      => '',
        //     "isSuperRole" => '',
        //     "status"      => '',
        //     "mchIdList"   => '',
        // ]);
        // $request = Context::set(ServerRequestInterface::class, $request);
        // return $handler->handle($request);

        $isValidToken = false;
        // $isApiType = false;
        // 根据具体业务判断逻辑走向，这里假设用户携带的token有效
        $token = $request->getHeaderLine('Authorization') ?? '';

        $data = null;

        if (strlen($token) > 0) {
            $token = JWTUtil::handleToken($token);
            CustomUtils::xzxDebug($token);
            if ($token !== false ) {
                try {
                    $this->jwt->checkToken($token);
                } catch (\Throwable $th) {
                    //throw $th;
                    throw new TokenValidException(XZXResponseCode::getMessage(XZXResponseCode::TOKEN_EXPIRE_CODE), XZXResponseCode::TOKEN_EXPIRE_CODE);
                }
                $isValidToken = true;
            }

            $data = $this->jwt->getParserData();
            if($data['jwt_scene'] != 'adminapi')
            {
                $isValidToken = false;
            }
            CustomUtils::xzxDebug($data);

            if ($data['user']->status != 1) {
                throw new TokenValidException(XZXResponseCode::getMessage(XZXResponseCode::LOGIN_FORBIDDEN), XZXResponseCode::LOGIN_FORBIDDEN);
            }
        }


        // 验token通过
        if ($isValidToken) {

            $ext = array_merge($request->getAttribute("ext", []), [
                "user"        => (array)$data['user'],
                "role"        => (array)$data['role'],
                "createBy"    => $data['user']->username,
                "updateBy"    => $data['user']->username,
                "uid"         => $data["uid"],
                "roleId"      => $data['user']->roleId,
                "isSuperRole" => $data['user']->isSuperRole,
                "status"      => $data['user']->status,
                "mchIdList"   => $this->SysAdminService->getMchIdListByAdminId($data["uid"])
            ]);

            CustomUtils::xzxDebug($ext);

            // 全局修改$request，后面控制器需要接受ext
            $request = $request->withAttribute("ext", $ext);
            $request = Context::set(ServerRequestInterface::class, $request);

            return $handler->handle($request);

        } else {
            throw new TokenValidException(XZXResponseCode::getMessage(XZXResponseCode::TOKEN_ERROR_CODE), XZXResponseCode::TOKEN_ERROR_CODE);
        }
    }
}
